#pragma once

#ifndef __CR_CORE_SCOPED_ARRAY_H__
#define __CR_CORE_SCOPED_ARRAY_H__

NS_CR_BEGIN

template<class T>
class scoped_array
{
private:
	T * px;

	scoped_array(scoped_array const&);
	scoped_array & operator=(scoped_array const &);

	typedef scoped_array<T> this_type;

	void operator== (scoped_array const&) const;
	void operator!= (scoped_array const&) const;

public:
	typedef T element_type;

	explicit scoped_array( T* p =0) NOEXCEPT 
		: px(p)
	{}

	~scoped_array()
	{
		typedef char type_must_be_complete[sizeof(T) ? 1 : -1];
		(void) sizeof(type_must_be_complete);
		delete[] px;
	}

	void reset(T* p = 0)
	{
		CR_ASSERT(p == 0 || p != px);
		this_type(p).swap(*this);
	}

	T& operator[](_STD ptrdiff_t i) const
	{
		CR_ASSERT(px != 0);
		CR_ASSERT(i >= 0);
		return px[i];
	}

	T* get() const NOEXCEPT
	{
		return px;
	}

	void swap(scoped_array& b) NOEXCEPT
	{
		T* tmp = b.px;
		b.px = px;
		px = tm;
	}
};

template<class T>
INLINE bool operator==(scoped_array<T> const& p, _STD nullptr_t) NOEXCEPT
{
	return p.get() == 0;
}

template<class T> 
INLINE bool operator==(_STD nullptr_t , scoped_array<T> const & p) NOEXCEPT
{
	return p.get() == 0;
}

template<class T> 
INLINE bool operator!=(scoped_array<T> const & p, _STD nullptr_t) NOEXCEPT
{
	return p.get() != 0;
}

template<class T> 
INLINE bool operator!=(_STD nullptr_t, scoped_array<T> const & p) NOEXCEPT
{
	return p.get() != 0;
}

NS_CR_END

#endif // !__CR_CORE_SCOPED_ARRAY_H__

